package sensorBoard.io;

import java.util.Random;
import java.util.Vector;

import com.Constants;
import com.Event;
import com.LedsManager;
import com.sun.spot.resources.transducers.LEDColor;

import sensorBoard.ISensorBoardComponent;
import server.interfaces.IMobileAgentExecutionEngine;
import server.interfaces.ISensorBoardManager;

/**
 * This is the manager for the IO resource of the node. 
 * At moment the class support the LEDs and the SWITCHS
 * @author Francesco Aiello, Antonio Guerrieri, Raffaele Gravina
 *
 */
public class IOManager implements ISensorBoardManager {
	
	private IMobileAgentExecutionEngine executionEngine;
	private Vector ioResources;
	private Vector eventsToHandle;
	
	/**
	 * The manager needs only the execution engine, to reply with the backEvents sent from the components
	 * @param executionEngine
	 */
	public IOManager(IMobileAgentExecutionEngine executionEngine) {
		this.executionEngine = executionEngine;
		this.ioResources = new Vector();
		this.eventsToHandle = new Vector();
	}

	public synchronized void addResource(ISensorBoardComponent sensorBoardComponent) {
		this.ioResources.addElement(sensorBoardComponent);		
	}


	public synchronized void handleEvent(String sourceMA, Event backEvent) {
		this.eventsToHandle.addElement(backEvent);
		this.notifyAll();
	}
	
	/**
	 * This method is a "while-true" cycle. At beginning it waits for incoming events by waitForEventsToHandle method.
	 * When an event arrives a searching for the right component starts.
	 */
	public void run () {
		
		while(true){
			waitForEventsToHandle();
			try {
				for (int i = 0; i < this.eventsToHandle.size(); i++) {
					Event backEvent = (Event)this.eventsToHandle.elementAt(i);					
					for (int j = 0; j < this.ioResources.size(); j++) {
						ISensorBoardComponent sensorBoardComponent = (ISensorBoardComponent)this.ioResources.elementAt(j);
						byte eventName = backEvent.getName();
						if ( sensorBoardComponent.IsEventHandlable(eventName)) { 
							sensorBoardComponent.handleEvent(backEvent);
						}
					}
				}
				this.eventsToHandle = new Vector();
			}
			catch (Exception e) {		
				LedsManager.error(LEDColor.YELLOW);
				e.printStackTrace();
			}
		}
	}
	
	/**
	 * This method is a "while-true" cycle.
	 * Until the size of the events vector is 0, the function waits by "wait()" method
	 */
	private synchronized void  waitForEventsToHandle() {
		
		while (this.eventsToHandle.size() == 0) {
			try {
				wait();
			}
			catch (InterruptedException e) {
				LedsManager.error(LEDColor.YELLOW);
				e.printStackTrace();
			}
		}
	}

	public void send(Event event) {
		this.executionEngine.send(event.getSourceID(), event.getTargetID(), event, false);
		
	}
	
	public String generateSensorBoardComponentID() {
		
		return "" + new Random().nextInt(Constants.MAX_RESOURCE_ID);
	}
}
